package udp;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 基于UDP的客户端
 */
public class UDPEchoClient {
    // 声明一个DatagramSocket对象，UDP套接字，用于发送和接收数据
    private DatagramSocket socket;
    // 声明服务器的IP地址
    private String serverIp;
    // 声明服务器的端口号
    private int serverPort;

    // 通过构造方法指定的服务器IP和端口号
    public UDPEchoClient (String serverIp, int serverPort) throws SocketException {
        // 初始化DatagramSocket对象，创建未绑定的UDP套接字，系统自动分配端口
        this.socket = new DatagramSocket();
        // 指定服务器IP和端口号
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }

    /**
     * 客户端服务
     *
     * @throws IOException
     */
    public void start () throws IOException {
        System.out.println("客户端已启动.");
        // 循环处理客户端的输入，持续与用户交互
        while (true) {
            System.out.println("->");// 提示用户输入
            // 定义Scanner，创建控制台输入扫描器
            Scanner scanner = new Scanner(System.in);
            // 1. 获取用户的输入
            String request = scanner.nextLine();
            // 验证输入不为空
            if (request == null || request.isEmpty()) {
                System.out.println("不能输入空字符串.");
                continue; // 跳过本次循环，等待下次输入
            }
            // 2. 创建目标的SocketAddress对象，服务器地址对象
            SocketAddress address = new InetSocketAddress(serverIp, serverPort);
            // 3. 定义一个用于包装用户请求数据的DatagramPacket--创建请求数据包
            DatagramPacket requestPacket = new DatagramPacket(
                    request.getBytes(StandardCharsets.UTF_8),// 请求数据字节数组
                    0, // 偏移量
                    request.getBytes().length,// 数据长度
                    address);// 服务器地址
            // 4. 发送请求到服务器
            socket.send(requestPacket);
            // 5. 用DatagramPacket接收服务器的响应的数据--创建接收数据包
            DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);
            // 6. 接收数据
            socket.receive(responsePacket);// 阻塞等待服务器响应
            // 7. 解析数据得到响应
            String response = new String(
                    responsePacket.getData(),
                    0,
                    responsePacket.getLength(),
                    "UTF-8");
            // 8. 打印打印请求和响应结果
            System.out.printf("request = %s, response = %s\n", request, response);
        }
    }

    public static void main(String[] args) throws IOException {
        // 创建客户端实例，连接到本地回环地址(127.0.0.1)的8888端口
        UDPEchoClient client = new UDPEchoClient("127.0.0.1", 8888);
        client.start();// 启动客户端
    }
}
